home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / mkproto.exe / MKPROTOH.C < prev    next >
Text File  |  1993-04-29  |  13KB  |  699 lines

  1. /*  VERSION=#(#):8,596,0, $*/
  2. #include <stddef.h>
  3. #include <stdlib.h>
  4.  
  5. #define EXIT_SUCCESS  0
  6. #define EXIT_FAILURE  1
  7.  
  8. #include <malloc.h>
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <string.h>
  13.  
  14. FILE *fOut=stdout;
  15.  
  16. static char szHdr[]="\n"\
  17. "/*****************************************************************************\n"\
  18. " *    %-10s        \n"\
  19. " ****************************************************************************/\n\n";
  20.  
  21. #define ISCSYM(x) ((x) > 0 && (isalnum(x) || (x) == '_'))
  22. #define ABORTED ( (Word *) -1 )
  23. #define MAXPARAM 20            /* max. number of parameters to a function */
  24. #define NEWBUFSIZ (20480*sizeof(char)) /* new buffer size */
  25.  
  26. int inquote = 0;               /* in a quote?? */
  27. int newline_seen = 1;          /* are we at the start of a line */
  28. long linenum  = 1L;            /* line number in current file */
  29. int dostatic = 0;              /* do static functions? */
  30. int dohead   = 1;              /* do file headers? */
  31. int glastc   = ' ';            /* last char. seen by getsym() */
  32.  
  33. typedef struct word 
  34. {
  35.     struct word *next;
  36.     char   string[1];
  37. } Word;
  38.  
  39. #include "mkprotoh.h"
  40.  
  41. /*
  42.  * Routines for manipulating lists of words.
  43.  */
  44.  
  45. Word *word_alloc(s)
  46. char *s;
  47. {
  48.     Word *w;
  49.  
  50.     w = (Word *) malloc(sizeof(Word) + strlen(s) + 1); /* ++jrb */
  51.     strcpy(w->string, s);
  52.     w->next = NULL;
  53.     return w;
  54. }
  55.  
  56. void word_free(w)
  57. Word *w;
  58. {
  59.     Word *oldw;
  60.     while (w) 
  61.     {
  62.         oldw = w;
  63.         w = w->next;
  64.         free(oldw);
  65.     }
  66. }
  67.  
  68. /* return the length of a list; empty words are not counted */
  69. int
  70. List_len(w)
  71. Word *w;
  72. {
  73.     int count = 0;
  74.  
  75.     while (w) 
  76.     {
  77.         if (*w->string) count++;
  78.         w = w->next;
  79.     }
  80.     return count;
  81. }
  82.  
  83. /* Append two lists, and return the result */
  84.  
  85. Word *word_append(w1, w2)
  86. Word *w1, *w2;
  87. {
  88.     Word *r, *w;
  89.  
  90.     r = w = word_alloc("");
  91.  
  92.     while (w1) 
  93.     {
  94.         w->next = word_alloc(w1->string);
  95.         w = w->next;
  96.         w1 = w1->next;
  97.     }
  98.     while (w2) 
  99.     {
  100.         w->next = word_alloc(w2->string);
  101.         w = w->next;
  102.         w2 = w2->next;
  103.     }
  104.  
  105.     return r;
  106. }
  107.  
  108. /* see if the last entry in w2 is in w1 */
  109.  
  110. int
  111. foundin(w1, w2)
  112. Word *w1, *w2;
  113. {
  114.     while (w2->next)
  115.         w2 = w2->next;
  116.  
  117.     while (w1) 
  118.     {
  119.         if (!strcmp(w1->string, w2->string))
  120.             return 1;
  121.         w1 = w1->next;
  122.     }
  123.     return 0;
  124. }
  125.  
  126. /* add the string s to the given list of words */
  127.  
  128. void addword(w, s)
  129. Word *w; 
  130. char *s;
  131. {
  132.     while (w->next) w = w->next;
  133.     w->next = word_alloc(s);
  134. }
  135.  
  136. /* given a list representing a type and a variable name, extract just
  137.  * the base type, e.g. "struct word *x" would yield "struct word"
  138.  */
  139.  
  140. Word *typelist(p)
  141. Word *p;
  142. {
  143.     Word *w, *r;
  144.  
  145.     r = w = word_alloc("");
  146.     while (p && p->next) 
  147.     {
  148.         if (p->string[0] && !ISCSYM(p->string[0]))
  149.             break;
  150.         w->next = word_alloc(p->string);
  151.         w = w->next;
  152.         p = p->next;
  153.     }
  154.     return r;
  155. }
  156.  
  157. /* typefixhack: promote formal parameters of type "char", "unsigned char",
  158.    "short", or "unsigned short" to "int".
  159. */
  160.  
  161. void typefixhack(w)
  162. Word *w;
  163. {
  164.     Word *oldw = 0;
  165.  
  166.     while (w) 
  167.     {
  168.         if (*w->string) 
  169.         {
  170.             if ( (!strcmp(w->string, "char") ||
  171.                 !strcmp(w->string, "short") )
  172.                 && (List_len(w->next) < 2) )
  173.             {
  174.                 if (oldw && !strcmp(oldw->string, "unsigned")) 
  175.                 {
  176.                     oldw->next = w->next;
  177.                     free(w);
  178.                     w = oldw;
  179.                 }
  180.                 strcpy(w->string, "int");
  181.             }
  182.         }
  183.         w = w->next;
  184.     }
  185. }
  186.  
  187. /* read a character: if it's a newline, increment the line count */
  188.  
  189. int ngetc(f)
  190. FILE *f;
  191. {
  192.     int c;
  193.  
  194.     c = getc(f);
  195.     if (c == '\n') linenum++;
  196.  
  197.     return c;
  198. }
  199.  
  200. /* read the next character from the file. If the character is '\' then
  201.  * read and skip the next character. Any comment sequence is converted
  202.  * to a blank.
  203.  */
  204.  
  205. int fnextch(f)
  206. FILE *f;
  207. {
  208.     int c, lastc, incomment;
  209.  
  210.     c = ngetc(f);
  211.     while (c == '\\') 
  212.     {
  213.         c = ngetc(f);   /* skip a character */
  214.         c = ngetc(f);
  215.     }
  216.     if (c == '/' && !inquote) 
  217.     {
  218.         c = ngetc(f);
  219.         if (c == '*') 
  220.         {
  221.             incomment = 1;
  222.             c = ' ';
  223.             while (incomment) 
  224.             {
  225.                 lastc = c;
  226.                 c = ngetc(f);
  227.                 if (lastc == '*' && c == '/')
  228.                     incomment = 0;
  229.                 else if (c < 0)
  230.                     return c;
  231.             }
  232.             return fnextch(f);
  233.         }
  234.         else
  235.         if(c=='/')
  236.         {
  237.             incomment = 1;
  238.             while (incomment) 
  239.             {
  240.                 c = ngetc(f);
  241.                 if(c=='\n')
  242.                 {
  243.                     incomment = 0;
  244.                     linenum--;
  245.                 }
  246.                 else if (c < 0)
  247.                     return c;
  248.             }
  249.             return fnextch(f);
  250.         }
  251.         else 
  252.         {
  253.             if (c == '\n') linenum--;
  254.             ungetc(c, f);
  255.             return '/';
  256.         }
  257.     }
  258.     return c;
  259. }
  260.  
  261.  
  262. /* Get the next "interesting" character. Comments are skipped, and strings
  263.  * are converted to "0". Also, if a line starts with "#" it is skipped.
  264.  */
  265.  
  266. int nextch(f)
  267. FILE *f;
  268. {
  269.     int c;
  270.  
  271.     c = fnextch(f);
  272.     if (newline_seen && c == '#') 
  273.     {
  274.         do 
  275.         {
  276.             c = fnextch(f);
  277.         } 
  278.         while (c >= 0 && c != '\n');
  279.         if (c < 0)
  280.             return c;
  281.     }
  282.     newline_seen = (c == '\n');
  283.  
  284.     if (c == '\'' || c == '\"') 
  285.     {
  286.         inquote = c;
  287.         while ( (c = fnextch(f)) >= 0 ) 
  288.         {
  289.             if (c == inquote) 
  290.             {
  291.                 inquote = 0;
  292.                 return '0';
  293.             }
  294.         }
  295.     }
  296.     return c;
  297. }
  298.  
  299. /*
  300.  * Get the next symbol from the file, skipping blanks.
  301.  * Return 0 if OK, -1 for EOF.
  302.  * Also collapses everything between { and 
  303. }
  304.  */
  305.  
  306. int
  307. getsym(buf, f)
  308. char *buf; 
  309. FILE *f;
  310. {
  311.     register int c;
  312.     int inbrack = 0;
  313.  
  314.     c = glastc;
  315.     while ((c > 0) && isspace(c)) 
  316.     {
  317.         c = nextch(f);
  318.     }
  319.     if (c < 0) 
  320.     {
  321.         return -1;
  322.     }
  323.     if (c == '{') 
  324.     {
  325.         inbrack = 1;
  326.         while (inbrack) 
  327.         {
  328.             c = nextch(f);
  329.             if (c < 0) 
  330.             {
  331.                 glastc = c;
  332.                 return c;
  333.             }
  334.             if (c == '{') inbrack++;
  335.             else if (c == '}') inbrack--;
  336.         }
  337.         strcpy(buf, "{}");
  338.         glastc = nextch(f);
  339.         return 0;
  340.     }
  341.     if (!ISCSYM(c)) 
  342.     {
  343.         *buf++ = c;
  344.         *buf = 0;
  345.         glastc = nextch(f);
  346.         return 0;
  347.     }
  348.     while (ISCSYM(c)) 
  349.     {
  350.         *buf++ = c;
  351.         c = nextch(f);
  352.     }
  353.     *buf = 0;
  354.     glastc = c;
  355.     return 0;
  356. }
  357.  
  358. /*
  359.  * skipit: skip until a ";" or the end of a function declaration is seen
  360.  */
  361. int skipit(buf, f)
  362. char *buf;
  363. FILE *f;
  364. {
  365.     int i;
  366.  
  367.     do 
  368.     {
  369.         i = getsym(buf, f);
  370.         if (i < 0) return i;
  371.     } 
  372.     while (*buf != ';' && *buf != '{');
  373.  
  374.     return 0;
  375. }
  376.  
  377. /*
  378.  * Get a parameter list; when this is called the next symbol in line
  379.  * should be the first thing in the list.
  380.  */
  381.  
  382. Word *getparamlist(f)
  383. FILE *f;
  384. {
  385.     static Word *pname[MAXPARAM]; /* parameter names */
  386.     Word    *tlist,         /* type name */
  387.     *plist;         /* temporary */
  388.     int     np = 0;         /* number of parameters */
  389.     int     typed[MAXPARAM];  /* parameter has been given a type */
  390.     int     tlistdone;      /* finished finding the type name */
  391.     int     sawsomething;
  392.     int     i;
  393.     int     inparen = 0;
  394.     char buf[80];
  395.  
  396.     for (i = 0; i < MAXPARAM; i++)
  397.         typed[i] = 0;
  398.  
  399.     plist = word_alloc("");
  400.  
  401.     /* first, get the stuff inside brackets (if anything) */
  402.  
  403.     sawsomething = 0;       /* gets set nonzero when we see an arg */
  404.     for (;;) 
  405.     {
  406.         if (getsym(buf, f) < 0) return NULL;
  407.         if (*buf == ')' && (--inparen < 0)) 
  408.         {
  409.             if (sawsomething) {     /* if we've seen an arg */
  410.                 pname[np] = plist;
  411.                 plist = word_alloc("");
  412.                 np++;
  413.             }
  414.             break;
  415.         }
  416.         if (*buf == ';') {      /* something weird */
  417.             return ABORTED;
  418.         }
  419.         sawsomething = 1;       /* there's something in the arg. list */
  420.         if (*buf == ',' && inparen == 0) 
  421.         {
  422.             pname[np] = plist;
  423.             plist = word_alloc("");
  424.             np++;
  425.         }
  426.         else 
  427.             {
  428.             addword(plist, buf);
  429.             if (*buf == '(') inparen++;
  430.         }
  431.     }
  432.  
  433.     /* next, get the declarations after the function header */
  434.  
  435.     inparen = 0;
  436.  
  437.     tlist = word_alloc("");
  438.     plist = word_alloc("");
  439.     tlistdone = 0;
  440.     sawsomething = 0;
  441.     for(;;) 
  442.     {
  443.         if (getsym(buf, f) < 0) return NULL;
  444.  
  445.         /* handle a list like "int x,y,z" */
  446.         if (*buf == ',' && !inparen) 
  447.         {
  448.             if (!sawsomething)
  449.                 return NULL;
  450.             for (i = 0; i < np; i++) 
  451.             {
  452.                 if (!typed[i] && foundin(plist, pname[i])) 
  453.                 {
  454.                     typed[i] = 1;
  455.                     word_free(pname[i]);
  456.                     pname[i] = word_append(tlist, plist);
  457.                     /* promote types */
  458.                     typefixhack(pname[i]);
  459.                     break;
  460.                 }
  461.             }
  462.             if (!tlistdone) 
  463.             {
  464.                 tlist = typelist(plist);
  465.                 tlistdone = 1;
  466.             }
  467.             word_free(plis